package wena

import (
	"context"
	"log"
	"os"
	"path/filepath"
	"sort"
	"time"

	_ "embed"

	"gitee.com/go-wena/proc"
	"gitee.com/go-wena/wena/internal/mod"
	"gitee.com/go-wena/wena/utils/httpx"
	"github.com/ghodss/yaml"
)

const (
	projectFileName = "wena.yml"
	envFileName     = "env.yml"
	gitVersionFlag  = ""

	tagListURL = "https://gitee.com/api/v5/repos/go-wena/app/tags"
)

//go:embed config.template.yml
var configTemplate []byte

type Project struct {
	Name        string `json:"name" yaml:"name"`
	Version     string `json:"version" yaml:"version"`
	Description string `json:"description" yaml:"description"`
	Output      string `json:"output" yaml:"output"`
	Depend      string `json:"depend" yaml:"depend"`
	Keep        bool   `json:"keep" yaml:"keep"`
}

func ProjectInit(ctx context.Context, modulePath string, overwrite, verbose bool) (err error) {
	if modulePath, err = createProjectMod(ctx, modulePath, verbose); err != nil {
		return
	}

	if err = createProjectFile(ctx, modulePath, overwrite); err != nil {
		return
	}

	if err = createProjectEnv(overwrite); err != nil {
		return
	}

	if stat, _ := os.Stat("wena.ignore"); stat == nil {
		_ = os.WriteFile("wena.ignore", nil, 0644)
	}

	return
}

func createProjectMod(ctx context.Context, modulePath string, verbose bool) (string, error) {
	log.Println("生成 go.mod")
	if mFile, _ := mod.Open("go.mod"); mFile != nil {
		if mFile.Package() != modulePath {
			log.Println("go.mod 已存在，模块路径为:", mFile.Package())
			return mFile.Package(), nil
		}
	} else {
		if err := proc.Context(ctx).Command("go", "mod", "init", modulePath).Verbose(verbose).Start(); err != nil {
			return modulePath, err
		}
	}
	return modulePath, nil
}

func createProjectFile(ctx context.Context, modulePath string, overwrite bool) (err error) {
	log.Printf("生成 %s", projectFileName)
	var proj Project
	if data, _ := os.ReadFile(projectFileName); len(data) > 0 {
		if !overwrite {
			log.Printf("%s 已存在，跳过", projectFileName)
			return nil
		}
		log.Printf("%s 已存在，覆盖", projectFileName)
		if err := yaml.Unmarshal(data, &proj); err != nil {
			return err
		}
	}

	proj.Name = filepath.Base(filepath.FromSlash(modulePath))
	if proj.Version == "" {
		proj.Version = gitVersionFlag
	}

	if proj.Depend == "" {
		var tags []struct {
			Name   string `json:"name"`
			Commit struct {
				Date time.Time `json:"date"`
			} `json:"commit"`
		}

		if err = httpx.Get(tagListURL).Process(httpx.ProcessJSON(&tags)).Exec(ctx); err != nil {
			return
		}

		if len(tags) > 0 {
			sort.SliceStable(tags, func(i, j int) bool { return tags[i].Commit.Date.After(tags[j].Commit.Date) })
			proj.Depend = tags[0].Name
		} else {
			proj.Depend = "v0.0.10"
		}
	}

	data, err := yaml.Marshal(&proj)
	if err != nil {
		return err
	}

	if err := os.WriteFile(projectFileName, data, 0644); err != nil {
		return err
	}

	return nil
}

func createProjectEnv(overwrite bool) (err error) {
	log.Printf("生成 %s", envFileName)
	if stat, _ := os.Stat(envFileName); stat != nil {
		if !overwrite {
			log.Printf("%s 已存在，跳过", envFileName)
			return nil
		}
		log.Printf("%s 已存在，覆盖", envFileName)
	}

	return os.WriteFile(envFileName, configTemplate, 0644)
}

func loadProject(pFn string) (proj Project, err error) {
	var data []byte

	if data, err = os.ReadFile(pFn); err != nil {
		return
	}

	if err = yaml.Unmarshal(data, &proj); err != nil {
		return
	}

	return
}
